#include "Outliner.h"
#include "ui_Outliner.h"

#include <list>
using namespace std;

#include <QtGui>

#include "Scene.h"
#include "Object.h"
#include "ObjMesh.h"
#include "Light.h"
#include "Camera.h"


//Q_DECLARE_METATYPE(Scene*)

namespace
{
enum ItemType
{
    SCENE_ITEM = 1001,
    OBJECT_ITEM = 1002,
    LIGHT_ITEM = 1003,
    CAMERA_ITEM = 1004
};
}


//***********************************************************
//                       Item Classes
//***********************************************************


class SceneItem : public QTreeWidgetItem
{
public:
    SceneItem(Scene* scene) :
        QTreeWidgetItem(SCENE_ITEM),
        scene(scene)
    {
        setText(0, "Scene");
        setIcon(0, QIcon(":/icons/scene.png"));

//        setFlags(flags() | Qt::ItemIsUserCheckable | Qt::ItemIsEditable);
//        setCheckState(1, Qt::Checked);
    }

    Scene* scene;
};

class ObjectItem : public QTreeWidgetItem
{
public:
    ObjectItem(Object* obj) :
        QTreeWidgetItem(OBJECT_ITEM),
        object(obj)
    {
        setText(0, QString::fromStdString(obj->getName()));
        //TODO: Usar o preview do objeto como ícone
        setIcon(0, QIcon(":/icons/object_item.png"));

        setFlags(flags() | /*Qt::ItemIsUserCheckable |*/ Qt::ItemIsEditable);
//        setCheckState(1, Qt::Checked);
    }

    Object* object;
};

class LightItem : public QTreeWidgetItem
{
public:
    LightItem(Light* l) :
        QTreeWidgetItem(LIGHT_ITEM),
        light(l)
    {
        setText(0, QString::fromStdString(l->getName()));
        setIcon(0, QIcon(":/icons/light_item.png"));

        setFlags(flags() | /*Qt::ItemIsUserCheckable |*/ Qt::ItemIsEditable);
//        setCheckState(1, Qt::Checked);
    }

    Light* light;
};

class CameraItem : public QTreeWidgetItem
{
public:
    CameraItem(Camera* c) :
        QTreeWidgetItem(CAMERA_ITEM),
        camera(c)
    {
        setText(0, "Camera");
        setIcon(0, QIcon(":/icons/camera.png"));

//        setFlags(flags() | Qt::ItemIsUserCheckable | Qt::ItemIsEditable);
//        setCheckState(1, Qt::Checked);
    }

    Camera* camera;
};

//***********************************************************



//***********************************************************
//                         Outliner
//***********************************************************

Outliner::Outliner(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Outliner)
{
    ui->setupUi(this);

    setWindowIcon(QIcon(":/icons/outliner.png"));

    ui->tree->setSelectionMode(QAbstractItemView::SingleSelection);
//    ui->tree->headerItem()->setIcon(1, QIcon(":/icons/eye.png"));
//    ui->tree->headerItem()->setText(1, "");

//    ui->tree->header()->setResizeMode(0, QHeaderView::ResizeToContents);
//    ui->tree->header()->setResizeMode(1, QHeaderView::Fixed);
//    ui->tree->header()->resizeSection(1, 16);

    connect(ui->tree, SIGNAL(itemSelectionChanged()), this, SLOT(onSelectionChanged()));
    connect(ui->tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), SLOT(onItemChanged(QTreeWidgetItem*, int)));
    connect(ui->tree, SIGNAL(itemPressed(QTreeWidgetItem*,int)), SLOT(onItemClicked(QTreeWidgetItem*, int)));


}

Outliner::~Outliner()
{
    delete ui;
}


void Outliner::setScene(Scene *scene)
{
    ui->tree->clear();

    m_scene = scene;

    SceneItem *sceneItem = new SceneItem(scene);
    ui->tree->addTopLevelItem(sceneItem);

    cameraItem = new CameraItem(scene->getCamera());
    sceneItem->addChild(cameraItem);

    lightsItem = new QTreeWidgetItem();
    lightsItem->setText(0, "Lights");
    lightsItem->setIcon(0, QIcon(":/icons/light.png"));
    sceneItem->addChild(lightsItem);

    list<Light*> lights = scene->getLights();
    for(list<Light*>::iterator it = lights.begin(); it != lights.end(); ++it)
        addLight(*it);

    objectsItem = new QTreeWidgetItem();
    objectsItem->setText(0, "Objects");
    objectsItem->setIcon(0, QIcon(":/icons/object.png"));
    sceneItem->addChild(objectsItem);
    list<Object*> objects = scene->getObjects();
    for(list<Object*>::iterator it = objects.begin(); it != objects.end(); ++it)
        addObject(*it);
}

void Outliner::addObject(Object *object)
{
    ObjectItem* item = new ObjectItem(object);
    objectsItem->addChild(item);

    ui->tree->setCurrentItem(item);
}

void Outliner::removeObject(Object *p)
{
//    PrimitiveItem* item = hash.value(p);
//    item->takeChildren();

//    if(p->parent())
//    {
//        PrimitiveItem* parent = hash.value(p->parent());
//        parent->removeChild(item);
//    }
//    else
//        ui->tree->topLevelItem(0)->removeChild(item);

//    hash.remove(p);
}

void Outliner::addLight(Light *light)
{
    LightItem *item = new LightItem(light);
    lightsItem->addChild(item);

    ui->tree->setCurrentItem(item);
}

void Outliner::removeLight(Light* light)
{

}


void Outliner::onItemClicked(QTreeWidgetItem *item, int col)
{
    if(QApplication::mouseButtons() == Qt::RightButton)
    {
        switch(item->type())
        {
        case LIGHT_ITEM:
        {
            if(col == 0)
            {
                QMenu menu;
                menu.addAction("Delete");
                QAction* ac = menu.exec(QCursor::pos());
                if(ac == 0)
                    return;

                if(ac->text() == "Delete")
                {
                    Light* light = static_cast<LightItem*>(item)->light;
                    lightsItem->removeChild(item);
                    delete item;

                    m_scene->removeLight(light);
                    delete light;

                    emit noSelection();
                    emit updated();
                }
            }

            break;
        }
        case OBJECT_ITEM:
        {
            if(col == 0)
            {
                QMenu menu;
                menu.addAction("Duplicate");
                menu.addSeparator();
                menu.addAction("Delete");
                QAction* ac = menu.exec(QCursor::pos());
                if(ac == 0)
                    return;

                if(ac->text() == "Duplicate")
                {
                    Object* oldObj = static_cast<ObjectItem*>(item)->object;
                    Object* newObj = Loader::loadObject(oldObj->getObjMesh()->getType(), QString::fromStdString(oldObj->getObjMesh()->getName()));
                    newObj->getTransform() = oldObj->getTransform();
                    newObj->setName(oldObj->getName() + "_copy");
                    m_scene->addObject(newObj);
                    addObject(newObj);

                    emit updated();
                }
                if(ac->text() == "Delete")
                {
                    Object* obj = static_cast<ObjectItem*>(item)->object;
                    objectsItem->removeChild(item);
                    delete item;

                    m_scene->removeObject(obj);
                    delete obj;

                    emit noSelection();
                    emit updated();
                }
            }

            break;
        }
        }
    }

    onSelectionChanged();
}

void Outliner::onSelectionChanged()
{
    QTreeWidgetItem *item = ui->tree->currentItem();

    switch(item->type())
    {
        case OBJECT_ITEM:
        {
            emit objectSelected(static_cast<ObjectItem*>(item)->object);
            break;
        }
        case LIGHT_ITEM:
        {
            emit lightSelected(static_cast<LightItem*>(item)->light);
            break;
        }
        default:
            emit noSelection();
    }
}


void Outliner::onItemChanged(QTreeWidgetItem *item, int col)
{
    switch(item->type())
    {
        case OBJECT_ITEM:
        {
            if(col == 0)
                static_cast<ObjectItem*>(item)->object->setName(item->text(0).toStdString());

            break;
        }
        case LIGHT_ITEM:
        {
            if(col == 0)
                static_cast<LightItem*>(item)->light->setName(item->text(0).toStdString());

            break;
        }
    }
}

void Outliner::resizeEvent(QResizeEvent *event)
{
    int s0 = event->size().width() - 50;
    ui->tree->header()->resizeSection(0, s0);
}

//***********************************************************
